#ifndef COMMON_H
#define COMMON_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <openssl/md5.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

#define DEFAULT_PORT 8888
#define DEFAULT_BLOCK_SIZE 4096  // 4KB
#define MAX_FILENAME_LENGTH 256
#define MAX_BUFFER_SIZE 1024 * 1024  // 1MB
#define MAX_CLIENTS 10
#define STATUS_FILE_EXT ".download"
#define TEMP_FILE_EXT ".part"

// 传输协议中的消息类型
typedef enum {
    MSG_FILE_REQUEST,      // 客户端请求文件
    MSG_FILE_INFO,         // 服务端发送文件信息
    MSG_BLOCK_REQUEST,     // 客户端请求块数据
    MSG_BLOCK_DATA,        // 服务端发送块数据
    MSG_TRANSFER_STATUS,   // 传输状态
    MSG_ERROR              // 错误消息
} MessageType;

// 文件信息结构体
typedef struct {
    char filename[MAX_FILENAME_LENGTH];
    off_t file_size;         // 文件大小
    int block_size;          // 块大小
    int total_blocks;        // 总块数
    char md5[33];            // 文件MD5值
} FileInfo;

// 块请求结构体
typedef struct {
    char filename[MAX_FILENAME_LENGTH];
    int block_index;         // 块索引
} BlockRequest;

// 块数据结构体
typedef struct {
    char filename[MAX_FILENAME_LENGTH];
    int block_index;         // 块索引
    int block_size;          // 块大小
    char md5[33];            // 块MD5值
    char data[];             // 块数据
} BlockData;

// 传输状态枚举
typedef enum {
    STATUS_NEW,              // 新文件
    STATUS_RESUME,           // 可续传
    STATUS_COMPLETE,         // 传输完成
    STATUS_ERROR             // 传输错误
} TransferStatus;

// 传输状态消息
typedef struct {
    char filename[MAX_FILENAME_LENGTH];
    TransferStatus status;   // 传输状态
    int block_index;         // 当前块索引（如果有）
    char message[256];       // 附加消息
} TransferStatusMsg;

// 消息头部
typedef struct {
    MessageType type;        // 消息类型
    int length;              // 消息长度
} MessageHeader;

// 计算文件的MD5值
int calculate_file_md5(const char *filename, char *md5_str);

// 计算内存块的MD5值
void calculate_block_md5(const void *data, size_t length, char *md5_str);

// 发送消息
ssize_t send_message(int sockfd, MessageType type, const void *data, size_t length);

// 接收消息
ssize_t receive_message(int sockfd, MessageHeader *header, void **data);

// 错误处理函数
void error_exit(const char *msg);

// 进度条显示函数
void print_progress(const char *filename, double progress, double speed, time_t elapsed);

#endif // COMMON_H